home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / Plug-in - Attr / NameAttribute.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-14  |  12.0 KB  |  493 lines  |  [TEXT/CWIE]

  1. /*
  2.  * Quickdraw 3D sample code
  3.  *
  4.  * This file shows how to implement a simple custom attribute as a plug-in.
  5.  *
  6.  * Nick Thompson, nickt@apple.com, November 1996
  7.  *
  8.  * Please send technical questions that you may have about this code
  9.  * to devsupport@apple.com
  10.  *
  11.  * Based on attributelib.  For more information about the basic principles
  12.  * of this, check the article in develop, plugins in the form of shared 
  13.  * libraries were just a twinkle in kent's eye then.  The main difference 
  14.  * is in the way these puppies get registered, and in the name sapce.
  15.  *
  16.  * This sample code has minimal error checking. More should be added if this
  17.  * code is used in a production quality product.
  18.  *
  19.  * Revision History:
  20.  *        8/12/97    RDD        Changed register and unregister functions and fixed
  21.  *                        CopyReplace method.
  22.  */
  23.  
  24. #include "QD3D.h"
  25. #include "QD3DExtension.h"
  26. #include "QD3DGeometry.h"
  27. #include "QD3DIO.h"
  28. #include "QD3DSet.h"
  29. #include "QD3DString.h"
  30. #include "QD3DView.h"
  31.  
  32. #include <Errors.h>
  33.  
  34. #include <string.h>
  35. #include "NameAttribute.h"
  36.  
  37.  
  38. /******************************************************************************
  39.  **        
  40.  **        Globals
  41.  **        
  42.  *****************************************************************************/
  43.  
  44. static TQ3XObjectClass             pNameAttributeClass = NULL;
  45.  
  46. static unsigned long            pSharedLibrary = 0;
  47. static const    short            pMajorVersion = 1 ;
  48. static const    short            pMinorVersion = 5 ;
  49.  
  50. /******************************************************************************
  51.  **        
  52.  **        Function prototypes for functions local to this file
  53.  **        
  54.  *****************************************************************************/ 
  55.  
  56. static TQ3Status        NameAttribute_Traverse(
  57.                             TQ3Object                unused,
  58.                             TQ3StringObject            *stringObject,
  59.                             TQ3ViewObject            view) ;
  60.  
  61. static TQ3Status        NameAttribute_ReadData(
  62.                             TQ3SetObject            attributeSet,
  63.                             TQ3FileObject            file) ;
  64.  
  65. static TQ3Status        NameAttribute_CopyAdd(
  66.                             TQ3StringObject            *src,
  67.                             TQ3StringObject            *dst) ;
  68.  
  69. static TQ3Status        NameAttribute_CopyReplace(
  70.                             TQ3StringObject            *src,
  71.                             TQ3StringObject            *dst) ;
  72.  
  73. static TQ3Status        NameAttribute_Delete(
  74.                             TQ3StringObject            *stringObject) ;
  75.     
  76. static TQ3XFunctionPointer NameAttribute_MetaHandler(
  77.                             TQ3XMethodType            methodType) ;
  78.  
  79.  
  80.  
  81. /*===========================================================================*\
  82.  *
  83.  *    Routine:    NameAttribute_SetName()
  84.  *
  85.  *    Comments:    Utility function to add a name on an shape object, geometry 
  86.  *                object, or attribute set.
  87.  *
  88. \*===========================================================================*/
  89.  
  90. TQ3Status    NameAttribute_SetName(
  91.     TQ3Object object, 
  92.     char    *name)
  93. {
  94.     TQ3StringObject            string = NULL;
  95.     TQ3AttributeSet            set = NULL;
  96.     TQ3Status                status = kQ3Success;
  97.     TQ3ElementType             myElementType ;
  98.     
  99.     /* 
  100.      * NOTE: You cannot just use the type as it was registered,
  101.      * so you have two options: the first is to save a reference 
  102.      * to the element type that we got back from the register function
  103.      * the second is to use the global class to get the type.  Since
  104.      * we already need to keep the class global, that's what I decided
  105.      * to do here. (This code is not optimal)
  106.      */
  107.      Q3XObjectClass_GetType( pNameAttributeClass, &myElementType) ;
  108.     
  109.     if( Q3Object_IsType(object, kQ3SharedTypeShape) == kQ3True ) {
  110.         
  111.         string = Q3CString_New(name);
  112.         
  113.         if( string == NULL) {
  114.             status = kQ3Failure;
  115.             goto cleanExit;
  116.         }
  117.             
  118.         if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  119.             
  120.             Q3Geometry_GetAttributeSet(object, &set);
  121.             
  122.             if( set == NULL ) {
  123.                 set = Q3AttributeSet_New();
  124.                 if( set == NULL ) {
  125.                     status = kQ3Failure;
  126.                     goto cleanExit;
  127.                 }
  128.                 Q3Geometry_SetAttributeSet(object, set);
  129.             }
  130.         } else {
  131.             Q3Shape_GetSet(object, &set);
  132.             
  133.             if( set == NULL ) {
  134.                 set = Q3Set_New();
  135.                 if( set == NULL ) {
  136.                     status = kQ3Failure;
  137.                     goto cleanExit;
  138.                 }
  139.                 Q3Shape_SetSet(object, set);
  140.             }
  141.         }    
  142.             
  143.         if( Q3Set_Add(set, myElementType, &string) == kQ3Failure ) {
  144.             status = kQ3Failure;
  145.             goto cleanExit;
  146.         }
  147.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  148.         string = Q3CString_New(name);
  149.         
  150.         if( string == NULL) {
  151.             status = kQ3Failure;
  152.             goto cleanExit;
  153.         }
  154.         
  155.         if( Q3AttributeSet_Add(object, myElementType, &string) == kQ3Failure ) {
  156.             status = kQ3Failure;
  157.             goto cleanExit;
  158.         }
  159.     } else 
  160.         status = kQ3Failure;
  161.         
  162. cleanExit:
  163.     if( string )
  164.         Q3Object_Dispose(string);
  165.     if( set )
  166.         Q3Object_Dispose(set);
  167.     return status;
  168. }
  169.  
  170. /*===========================================================================*\
  171.  *
  172.  *    Routine:    NameAttribute_GetName()
  173.  *
  174.  *    Comments:    Utility function to get a name from a shape object, geometry 
  175.  *                object, or an attribute set.
  176.  *
  177. \*===========================================================================*/
  178.  
  179. TQ3Status    NameAttribute_GetName(
  180.     TQ3Object object, 
  181.     char    *name)
  182. {
  183.     TQ3StringObject            string = NULL;
  184.     TQ3AttributeSet            set = NULL;
  185.     TQ3Status                status = kQ3Success;
  186.     char                    *nameString = NULL ;
  187.     TQ3ElementType             myElementType ;
  188.     
  189.     /* 
  190.      * NOTE: You cannot just use the type as it was registered,
  191.      * so you have two options: the first is to save a reference 
  192.      * to the element type that we got back from the register function
  193.      * the second is to use the global class to get the type.  Since
  194.      * we already need to keep the class global, that's what I decided
  195.      * to do here.  Set up the element type:
  196.      */
  197.      Q3XObjectClass_GetType( pNameAttributeClass, &myElementType) ;
  198.     
  199.     if( Q3Object_IsType(object, kQ3SharedTypeShape) == kQ3True ) {
  200.             
  201.         if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  202.             
  203.             Q3Geometry_GetAttributeSet(object, &set);
  204.             
  205.             if( set == NULL ) {
  206.                 status = kQ3Failure;
  207.                 goto cleanExit;
  208.             }
  209.             
  210.         } 
  211.         else 
  212.         {
  213.             Q3Shape_GetSet(object, &set);
  214.         }
  215.         
  216.         if( Q3Set_Contains ( set, myElementType ) == kQ3True ) {
  217.             status = Q3Set_Get ( set, myElementType, &string ) ;
  218.             if( string == NULL || status == kQ3Failure ) {
  219.                 status = kQ3Failure;
  220.                 goto cleanExit;
  221.             }
  222.         }
  223.         
  224.     } 
  225.     else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  226.  
  227.         if( Q3AttributeSet_Get(object, myElementType, &string) == kQ3Failure ) {
  228.             status = kQ3Failure;
  229.             goto cleanExit;
  230.         }
  231.         
  232.     } else 
  233.         status = kQ3Failure;
  234.     
  235.     if( status != kQ3Failure && string != NULL )
  236.     {
  237.         /* get the string from the CString object */
  238.         status = Q3CString_GetString ( string, &nameString ) ;
  239.         strcpy( name, nameString ) ;
  240.         status = Q3CString_EmptyData(&nameString);
  241.     }
  242.     else
  243.     {
  244.         *name = NULL ;
  245.     }
  246.         
  247. cleanExit:
  248.     if( string )
  249.         Q3Object_Dispose(string);
  250.  
  251.     if( set )
  252.         Q3Object_Dispose(set);
  253.     return status;
  254. }
  255.  
  256.  
  257. /*===========================================================================*\
  258.  *
  259.  *    Routine:    NameAttributeClassRegister()
  260.  *
  261.  *    Comments:    Registers the Name attribute class.
  262.  *
  263. \*===========================================================================*/
  264.  
  265. TQ3Status    NameAttribute_Register( void )
  266. {
  267.     TQ3ElementType     myElementType = kQ3ObjectTypeInvalid ;    /* discarded */
  268.  
  269.     /* 
  270.      * Register the new name element class.  NOTE: this will change myElementType
  271.      * to be a unique type.  This helps to prevent namespace clashes, but you MUST
  272.      * remember to use what you are passed back when accessing the elements of a set.
  273.      *
  274.      * You can either store the value returned in myElementType or use the global
  275.      * pNameAttributeClass.  In this sample we use the latter approach.  Now that we
  276.      * have a reference to the class around we can use that to get the type for 
  277.      * the calls that need the type using the following API call:
  278.      *
  279.      *      Q3XObjectClass_GetType( pNameAttributeClass, &myElementType) ;
  280.      */
  281.      
  282.     pNameAttributeClass =
  283.         Q3XElementClass_Register(
  284.             &myElementType,
  285.             kElementTypeNameString,
  286.             sizeof(TQ3StringObject),
  287.             NameAttribute_MetaHandler );
  288.     
  289.     if (pNameAttributeClass == NULL)
  290.         return kQ3Failure;
  291.     
  292.     return kQ3Success;
  293. }
  294.  
  295.  
  296. /* Name attribute CFM init and termination routines */
  297.  
  298. OSErr NameAttribute_ConnectionInitializationRoutine(InitBlockPtr initBlock)
  299. {
  300.     TQ3Status                theStatus;
  301.     TQ3XSharedLibraryInfo    sharedLibraryInfo;
  302.     OSErr                    osErr;
  303.  
  304.     /*
  305.      * Register this custom attribute/element with QuickDraw 3D using the
  306.      * callback Q3XSharedLibrary_Register which is passed the register function
  307.      * and the closureID (_not_ the connectionID).
  308.      */
  309.     sharedLibraryInfo.registerFunction = NameAttribute_Register;
  310.     sharedLibraryInfo.sharedLibrary    = (unsigned long)initBlock->connectionID;
  311.     theStatus = Q3XSharedLibrary_Register(&sharedLibraryInfo);
  312.  
  313.     if (theStatus == kQ3Success) {
  314.         pSharedLibrary = (unsigned long)initBlock->connectionID;
  315.         osErr = noErr;
  316.     }
  317.     else {
  318.         osErr = fragMgrInitErr; /* ...or some other meaningfull error */
  319.     }
  320.  
  321.     return osErr;
  322. }
  323.  
  324.  
  325.  
  326. void NameAttribute_ConnectionTerminationRoutine (void)
  327. {
  328.     TQ3Status theStatus ;
  329.     
  330.     if( pSharedLibrary != NULL ) {
  331.         theStatus = Q3XSharedLibrary_Unregister(pSharedLibrary);
  332.         pSharedLibrary = NULL;
  333.     }
  334.     
  335.     theStatus = NameAttribute_Unregister() ;
  336. }
  337.  
  338.  
  339. /*
  340.  * Static Functions
  341.  */
  342.  
  343. static TQ3Status NameAttribute_Traverse(
  344.     TQ3Object                unused,
  345.     TQ3StringObject            *stringObject,
  346.     TQ3ViewObject            view)
  347. {
  348.     (void) unused;
  349.     
  350.     if (stringObject == NULL || *stringObject == NULL)
  351.         return kQ3Success;
  352.  
  353.     if (Q3XView_SubmitWriteData(view, 0, NULL, NULL) == kQ3Failure) {
  354.         return kQ3Failure;
  355.     }
  356.  
  357.     if (Q3Object_Submit( *stringObject, view) == kQ3Failure) {
  358.         return kQ3Failure;
  359.     }
  360.  
  361.     return kQ3Success;
  362. }
  363.  
  364. static TQ3Status NameAttribute_ReadData(
  365.     TQ3SetObject            attributeSet,
  366.     TQ3FileObject            file)
  367. {
  368.     TQ3StringObject            stringObject;
  369.     TQ3Status                status;
  370.     
  371.     TQ3ElementType             myElementType ;
  372.     
  373.     /* 
  374.      * NOTE: You cannot just use the type as it was registered,
  375.      * so you have two options: the first is to save a reference 
  376.      * to the element type that we got back from the register function
  377.      * the second is to use the global class to get the type.  Since
  378.      * we already need to keep the class global, that's what I decided
  379.      * to do here.
  380.      */
  381.     Q3XObjectClass_GetType( pNameAttributeClass, &myElementType) ;
  382.  
  383.     stringObject = Q3File_ReadObject(file);
  384.         
  385.     status = Q3Set_Add(attributeSet, myElementType, &stringObject);
  386.     
  387.     Q3Object_Dispose(stringObject);
  388.  
  389.     /*
  390.      *    Note that the string object has a reference count of 1,
  391.      *    which will be taken care of in the dispose
  392.      */
  393.     return status;
  394. }
  395.  
  396. static TQ3Status NameAttribute_CopyAdd(
  397.     TQ3StringObject    *src,
  398.     TQ3StringObject    *dst)
  399. {
  400.     *dst = Q3Shared_GetReference(*src);
  401.  
  402.     return (*dst != NULL) ? kQ3Success : kQ3Failure;
  403. }
  404.  
  405. static TQ3Status NameAttribute_CopyReplace(
  406.     TQ3StringObject    *src,
  407.     TQ3StringObject    *dst)
  408. {
  409.     TQ3StringObject    tempString;
  410.     
  411.     /*
  412.      *    It is always good form to get a reference first,
  413.      *    in case src and dst point to the same object
  414.      */
  415.     
  416.     tempString = Q3Shared_GetReference(*src);
  417.     if (tempString == NULL) 
  418.         return kQ3Failure;
  419.  
  420.     if( *dst )
  421.         Q3Object_Dispose( *dst );
  422.     
  423.     *dst = tempString;
  424.  
  425.     return kQ3Success;
  426. }
  427.  
  428. static TQ3Status NameAttribute_Delete(
  429.     TQ3StringObject    *stringObject)
  430. {
  431.     if (*stringObject != NULL) {
  432.         Q3Object_Dispose(*stringObject);
  433.         *stringObject = NULL;
  434.     }
  435.  
  436.     return kQ3Success;
  437. }
  438.  
  439. TQ3Status NameAttribute_Unregister(
  440.     void)
  441. {
  442.     TQ3Status        returnVal = kQ3Failure ;
  443.     
  444.     if ( pNameAttributeClass != NULL )
  445.     {
  446.         /*
  447.          * QuickDraw 3D unregisters this object together with all
  448.          * other registered objects in the system on Q3Exit.
  449.          */
  450.         pNameAttributeClass = NULL ;
  451.         returnVal = kQ3Success ;
  452.     }    
  453.  
  454.     return returnVal ;
  455. }
  456.  
  457.  
  458.  
  459. /*
  460.  * NameAttribute_MetaHandler
  461.  */
  462. static TQ3XFunctionPointer NameAttribute_MetaHandler(
  463.     TQ3XMethodType        methodType)
  464. {
  465.     switch (methodType)
  466.     {
  467.         case kQ3XMethodTypeObjectClassVersion:
  468.             return (TQ3XFunctionPointer)
  469.                 Q3_OBJECT_CLASS_VERSION(pMajorVersion, pMinorVersion);
  470.  
  471.         case kQ3XMethodTypeObjectTraverse:
  472.             return (TQ3XFunctionPointer) NameAttribute_Traverse;
  473.  
  474.         case kQ3XMethodTypeObjectReadData:
  475.             return (TQ3XFunctionPointer) NameAttribute_ReadData;
  476.  
  477.         case kQ3XMethodTypeElementCopyAdd:
  478.         case kQ3XMethodTypeElementCopyGet:
  479.         case kQ3XMethodTypeElementCopyDuplicate:
  480.             return (TQ3XFunctionPointer) NameAttribute_CopyAdd;
  481.  
  482.         case kQ3XMethodTypeElementCopyReplace:
  483.             return (TQ3XFunctionPointer) NameAttribute_CopyReplace;
  484.  
  485.         case kQ3XMethodTypeElementDelete:
  486.             return (TQ3XFunctionPointer) NameAttribute_Delete;
  487.  
  488.         default:
  489.             return (TQ3XFunctionPointer) NULL;
  490.     }
  491. }
  492.  
  493.